/*
 * Copyright (c) 2009-2011, Petr Panteleyev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *    3. The name of the author may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.panteleyev.blogclient;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.EventObject;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

import org.panteleyev.blogclient.events.UserProfilesUpdatedEvent;
import org.panteleyev.blogclient.profwizard.NewProfileWizard;
import org.panteleyev.swing.BaseTable;
import org.panteleyev.swing.SwingFactory;
import org.panteleyev.swing.TableUtil;
import org.panteleyev.swing.UIStrings;
import org.panteleyev.utilities.events.AppEventListener;

/**
 *
 * @author Petr Panteleyev <petr@panteleyev.org>
 */
public class UserProfileListFrame extends BloggerFrame {
    private ArrayList<UserProfile<?>> profs;
    private JScrollPane scroller;
    private JTable profileTable;
    private AbstractTableModel tableModel;
    private AbstractAction editProfileAction;
    private AbstractAction createProfileAction;
    private AbstractAction deleteProfileAction;

    private static String[] header = {
        "",
        L10N.UPLF_TABLE_PROFILE.s(),
        L10N.UPLF_TABLE_SERVER.s()
    };

    public UserProfileListFrame() {
        profs = UserProfileManager.getProfiles();

        setTitle(AboutDialog.PRODUCT_NAME + " - " + L10N.UPLF_TITLE.s());
        setIconImage(Icon.BIG_LOGO.i().getImage());

        createActions();
        createMenuBar();
        createContent();

        addAppEventListener(UserProfilesUpdatedEvent.class, new AppEventListener() {
            @Override
            public void eventReceived(EventObject event) {
                onProfilesUpdated();
            }
        });

        Options.getBounds(this);
    }

    private void createMenuBar() {
        createMenuBar(
            createFileMenu(),
            createMenu(UIStrings.MENU_EDIT_NAME.s(), null,
                createProfileAction,
                editProfileAction,
                null,
                deleteProfileAction
            ),
            createToolsMenu(),
            createWindowMenu(),
            createHelpMenu()
        );
    }

    private void createActions() {
        createProfileAction = new AbstractAction(UIStrings.CREATE_ACTION.s(), Icon.EMPTY.i()) {
            @Override
            public void actionPerformed(ActionEvent e) {
                onCreateProfile();
            }
        };

        editProfileAction = new AbstractAction(UIStrings.EDIT_ACTION.s(), Icon.EDIT.i()) {
            @Override
            public void actionPerformed(ActionEvent e) {
                onEditProfile();
            }
        };

        deleteProfileAction = new AbstractAction(UIStrings.DELETE_ACTION.s(), Icon.DELETE.i()) {
            @Override
            public void actionPerformed(ActionEvent e) {
                onDeleteProfile();
            }
        };
    }

    private JPopupMenu createPopupMenu() {
        return SwingFactory.createMenu(null,
            createProfileAction,
            editProfileAction,
            null,
            deleteProfileAction
        ).getPopupMenu();
    }

    private void createContent() {
        tableModel = new AbstractTableModel() {
            @Override
            public int getColumnCount() {
                return header.length;
            }

            @Override
            public String getColumnName(int column) {
                return header[column];
            }

            @Override
            public int getRowCount() {
                return profs.size();
            }

            @Override
            public Class<?> getColumnClass(int columnIndex) {
                switch (columnIndex) {
                    case 0:
                        return ImageIcon.class;
                    default:
                        return String.class;
                }
            }

            @Override
            public Object getValueAt(int row, int column) {
                UserProfile<?> p = profs.get(row);
                if (p == null) {
                    return null;
                }

                switch (column) {
                    case 0:
                        return p.getIcon();
                    case 1:
                        return p.getName();
                    case 2:
                        return p.getServer();
                    default:
                        return null;
                }
            }
        };

        getContentPane().setLayout(new BorderLayout());

        profileTable = new BaseTable(tableModel);
        scroller = new JScrollPane(profileTable);
        scroller.setComponentPopupMenu(createPopupMenu());

        profileTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent evt) {
                if (evt.getClickCount() == 2) {
                    onDoubleClick();
                }
            }
        });

        scroller.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent evt) {
                TableUtil.adjustTableColumnSizes(profileTable, 2, scroller);
                TableUtil.adjustTableRowSizes(profileTable);
            }
        });

        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel);
        sorter.setSortable(0, false);
        profileTable.setRowSorter(sorter);

        profileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        profileTable.setShowGrid(false);
        getContentPane().add(scroller, BorderLayout.CENTER);

        scroller.getViewport().setBackground(profileTable.getBackground());
    }

    private UserProfile<?> getSelectedProfile() {
        final int row = profileTable.getSelectedRow();
        return (row == -1)? null : profs.get(profileTable.convertRowIndexToModel(row));
    }

    private void onCreateProfile() {
        NewProfileWizard dial = new NewProfileWizard(this);
        if (dial.showDialog()) {
            profs = UserProfileManager.getProfiles();
            tableModel.fireTableDataChanged();
            TableUtil.adjustTableColumnSizes(profileTable, 2, scroller);
            TableUtil.adjustTableRowSizes(profileTable);
            UserProfileManager.saveProfiles();
        }

    }

    private void onEditProfile() {
        UserProfile<?> selectedProfile = getSelectedProfile();
        if (selectedProfile != null) {
            String oldName = selectedProfile.getName();
            ProfileDialog profDial = selectedProfile.createProfileDialog(this);

            if ((profDial != null) && (profDial.showDialog())) {
                UserProfileManager.updateProfile(oldName, selectedProfile);
                UserProfileManager.saveProfiles();
                profs = UserProfileManager.getProfiles();
                tableModel.fireTableDataChanged();
                TableUtil.adjustTableColumnSizes(profileTable, 2, scroller);
                TableUtil.adjustTableRowSizes(profileTable);
            }
        }
    }

    private void onDeleteProfile() {
        int index = profileTable.getSelectedRow();
        if (index != -1) {
            UserProfile<?> prof = (UserProfile<?>)profs.get(index);
            if (prof.isConnected()) {
                JOptionPane.showMessageDialog(this, "Active profile cannot be deleted.\nPlease disconnect first.");
            } else {
                if (MainClass.showConfirmDialog(this)) {
                    UserProfileManager.deleteProfile(prof);
                    profs = UserProfileManager.getProfiles();
                    tableModel.fireTableDataChanged();
                    TableUtil.adjustTableColumnSizes(profileTable, 2, scroller);
                    TableUtil.adjustTableRowSizes(profileTable);
                }
            }
        }
    }

    private void onProfilesUpdated() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                profs = UserProfileManager.getProfiles();
                tableModel.fireTableDataChanged();
                TableUtil.adjustTableColumnSizes(profileTable, 2, scroller);
                TableUtil.adjustTableRowSizes(profileTable);
            }
        });
    }

    private void onDoubleClick() {
        UserProfile<?> prof = getSelectedProfile();

        if (prof == null || prof.isConnected()) {
            return;
        }

        LoginDialog dial = new LoginDialog(this);

        dial.autoLogin(prof);

        if (dial.isLoggedIn()) {
            prof.postLoginUIActions();
            prof.openStartupWindow();
        }
    }
}
